package io.grpc.benchmarks.qps;

import com.google.common.base.Preconditions;
import org.HdrHistogram.Histogram;

import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HistogramFuture implements Future<Histogram> {
    private final Histogram histogram;
    private boolean canceled;
    private boolean done;

    HistogramFuture(Histogram histogram) {
        Preconditions.checkNotNull(histogram, "histogram");
        this.histogram = histogram;
    }

    @Override
    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
        if (!done && !canceled) {
            canceled = true;
            notifyAll();
            return true;
        }
        return false;
    }

    @Override
    public synchronized boolean isCancelled() {
        return canceled;
    }

    @Override
    public synchronized boolean isDone() {
        return done || canceled;
    }

    @Override
    public synchronized Histogram get()
            throws InterruptedException, ExecutionException {
        while (!isDone() && !isCancelled()) {
            wait();
        }

        if (isCancelled()) {
            throw new CancellationException();
        }

        done = true;
        return histogram;
    }

    @Override
    public Histogram get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException {
        throw new UnsupportedOperationException();
    }

    protected synchronized void done() {
        done = true;
        notifyAll();
    }
}